﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "GbmpAutoRecognizeStructureFloorParameterDlg.h"
#include "ISelection.h"
#include "IGraphicsNodeReference.h"
#include "GbmpBuiltInCategoryUniIdentitiesNew.h"
#include "IDocument.h"
#include "IFamily.h"
#include "IFamilyType.h"
#include "IElement.h"
#include "IGenericElement.h"
#include "IElementBasicInformation.h"
#include "LevelUtils.h"
#include "BuiltInStructureFamilies.h"
#include "GmStyleSheetHelper.h"
#include "StructureDefaultFamilyNames.h"
#include "StructureFamilyUiUtils.h"
#include "GbmpDocUtils.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;

GbmpAutoRecognizeStructureFloorParameterDlg::GbmpAutoRecognizeStructureFloorParameterDlg(IDocument* pDoc, const ElementId levelId, QWidget* parent)
    : QDialog(parent, Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint)
    , m_pDocument(pDoc)
{
    m_ui.setupUi(this);

    // 设置gbmp对话框标题样式
    std::wstring styleSheetString = GmStyleSheetHelper::Instance()->GetCurrentStyleData();
    setStyleSheet(QString::fromStdWString(styleSheetString));
    this->setProperty("use_gbmp_title", true);
    m_ui.gbmp_title->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
    m_ui.gbmp_title->setIconVisible(false);
    m_ui.gbmp_title->setMaxButtonVisible(false);
    m_ui.gbmp_title->setMinButtonVisible(false);
    m_ui.gbmp_title->setText(QString::fromStdWString(GBMP_TR(L"自动识别")));

    connect(m_ui.gbmp_title, &GmTitleBar::closeRequested, this, &GbmpAutoRecognizeStructureFloorParameterDlg::reject);
    connect(m_ui.gbmp_title, &GmTitleBar::moveRequested, this, &GbmpAutoRecognizeStructureFloorParameterDlg::OnMoveRequested);

    InitComponent(levelId);

    connect(m_ui.okButton, SIGNAL(clicked()), this, SLOT(OnClickOk()));
    connect(m_ui.cancelButton, SIGNAL(clicked()), this, SLOT(OnClickCancel()));
    connect(m_ui.buildingStoreyInput, SIGNAL(currentIndexChanged(int)), this, SLOT(OnWorkLevelChanged(int)));
}

void GbmpAutoRecognizeStructureFloorParameterDlg::OnClickOk()
{
    m_param.floorFamilyName = m_ui.floorTypeInput->currentData().toString().toStdWString();
    m_param.floorType = m_ui.floorTypeInput->currentText().toStdWString();
    m_param.topLevelOffset = m_ui.topLevelOffsetInput->text().toDouble();
    m_param.isFromSelected = m_ui.selectByInteraction->isChecked();
    m_param.buildingStoreyLevelId = ElementId(m_ui.buildingStoreyInput->currentData().toLongLong());
    m_param.topLevelId = ElementId(m_ui.topLevelInput->currentData().toLongLong());
    this->accept();
}
void GbmpAutoRecognizeStructureFloorParameterDlg::OnClickCancel()
{
    close();
}
void GbmpAutoRecognizeStructureFloorParameterDlg::OnMoveRequested(const QPoint& cursorPos, const QPoint& offset)
{
    Q_UNUSED(cursorPos);
    move(pos() + offset);
}
void GbmpAutoRecognizeStructureFloorParameterDlg::OnWorkLevelChanged(int index)
{
    ElementId id = ElementId(m_ui.buildingStoreyInput->currentData().toLongLong());
    ResetLevel(id);
}

std::vector<ElementId> GbmpAutoRecognizeStructureFloorParameterDlg::GetSelectedElements()
{
    std::vector<ElementId> selectedElements;
    if (!GetDocument())
    {
        return selectedElements;
    }

    // 多选Element
    const GraphicsNodeReferenceOwnerPtrSet& nodeRefSets = ISelection::Get()->GetGraphicsNodeReferences();
    FOR_EACH(selectedItem, nodeRefSets)
    {
        ElementId selectedId = selectedItem->GetElementId();
        selectedElements.push_back(selectedId);
    }

    return selectedElements;
}

void GbmpAutoRecognizeStructureFloorParameterDlg::ResetFloorType()
{
    const IDocument* pDoc = GetDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    m_ui.floorTypeInput->clear();
    
    std::vector<IFamily*> pFloorFamilies;
    std::vector<IFamily*> pAllFamilies = IFamily::GetAllFamilies(pDoc);
    FOR_EACH(pFloorFamily, pAllFamilies)
    {
        if (pFloorFamily->GetBasicInformation()->GetCategoryUid().HasSameValue(BuiltInCategoryUniIdentities::BICU_STRUCTURE_FLOOR))
        {
            pFloorFamilies.push_back(pFloorFamily);
        }
    }
    FOR_EACH(pFamily, pFloorFamilies)
    {
        if (!pFamily)
        {
            continue;
        }
        std::vector<const IFamilyType*> pFamilyTypes = pFamily->GetFamilyTypes();
        FOR_EACH(pFamilyType, pFamilyTypes)
        {
            m_ui.floorTypeInput->addItem(QString::fromStdWString(pFamilyType->GetName()), QVariant(QString::fromStdWString(pFamily->GetBasicInformation()->GetName())));
        }
    }
}

void GbmpAutoRecognizeStructureFloorParameterDlg::ResetLevel(const ElementId thisLevelId)
{
    const IDocument* pDoc = GetDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    this->m_param.topLevelId = thisLevelId;

    ILevel* pLevel = LevelUtils::GetLevelById(pDoc, thisLevelId);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pLevel, L"pLevel为空",L"GDMPLab",L"2024-03-30");

    double levelElevation = pLevel->GetElevation();
    const ILevel* pHigherLevel = LevelUtils::GetHigherStoreyLevel(pDoc, levelElevation);

    if (pHigherLevel)
    {
        ElementId higherLevelId = pHigherLevel->GetOwnerElement()->GetElementId();
        DBG_WARN_AND_RETURN_VOID_UNLESS(higherLevelId.IsValid(), L"higherLevelId无效",L"GDMPLab",L"2024-03-30");
        for (int idx = 0; idx < m_ui.topLevelInput->count(); ++idx)
        {
            if (higherLevelId.AsInt64() == m_ui.topLevelInput->itemData(idx).toLongLong())
            {
                m_ui.topLevelInput->setCurrentIndex(idx);
                break;
            }
        }
        m_param.topLevelOffset = 0.0;
    }
    else
    {
        // 顶部标高与所属楼层相同
        int idx = m_ui.buildingStoreyInput->currentIndex();
        DBG_WARN_AND_RETURN_VOID_UNLESS(idx >= 0 && idx < m_ui.topLevelInput->count(), L"所属楼层个数和顶部标高个数不同?",L"GDMPLab",L"2024-03-30");
        m_ui.topLevelInput->setCurrentIndex(idx);
        m_param.topLevelOffset = 3000;
    }

    m_ui.topLevelOffsetInput->setText(QString::number(m_param.topLevelOffset, 'f', 2));
}

void GbmpAutoRecognizeStructureFloorParameterDlg::InitComponent(const ElementId thisLevelId)
{
    IDocument* pDoc = GetDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    // 按当前工作楼层/按选择范围
    std::vector<ElementId> selectedElements = GetSelectedElements();
    if (selectedElements.empty())
    {
        m_ui.selectByCurrentWorkStorey->setChecked(true);
    }
    else
    {
        m_ui.selectByInteraction->setChecked(true);
    }

    // 重置楼板类型
    ResetFloorType();

    if (m_ui.floorTypeInput->count() == 0)
    {
        // 载入楼板族
        StructureFamilyUiUtils::FamilyCreators defaultFamilyCreators
        {
            { DEFAULT_STRUCTURE_FLOOR_FAMILY_NAME, BuiltInStructureFamilies::CreateBuiltInFloorFamilyDocument }
        };
        StructureFamilyUiUtils::CreateFamilies(pDoc, defaultFamilyCreators);

        ResetFloorType();
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_ui.floorTypeInput->count() > 0, L"获取楼板类型失败",L"GDMPLab",L"2024-03-30");
    }

    // 所属楼层、顶部标高
    m_ui.buildingStoreyInput->clear();
    m_ui.topLevelInput->clear();

    std::vector<IElement*> pAllLevels = gcmp::GbmpDocUtils::GetElementsByCategory(pDoc, BuiltInCategoryUniIdentities::BICU_NEW_ELEVATION);
    FOR_EACH_INDEX(index, pAllLevels)
    {
        IGenericElement* pGenericElement = quick_cast<IGenericElement>(pAllLevels.at(index));
        DBG_WARN_AND_RETURN_VOID_UNLESS(pGenericElement, L"pGenericElement为空",L"GDMPLab",L"2024-03-30");
        ILevel* pLevel = quick_cast<ILevel>(pGenericElement->GetExternalObject());
        DBG_WARN_AND_RETURN_VOID_UNLESS(pLevel, L"pLevel为空",L"GDMPLab",L"2024-03-30");

        ElementId levelId = pLevel->GetOwnerElement()->GetElementId();
        std::wstring name = pLevel->GetOwnerElement()->GetBasicInformation()->GetName();
        m_ui.buildingStoreyInput->addItem(QString::fromStdWString(name),QVariant(levelId.AsInt64()));
        m_ui.topLevelInput->addItem(QString::fromStdWString(name), QVariant(levelId.AsInt64()));
        if (thisLevelId == levelId)
        {
            m_ui.buildingStoreyInput->setCurrentIndex(index);
        }
    }

    // 当前所属楼层
    ResetLevel(thisLevelId);
}

const StructureFloorCreateParameter GbmpAutoRecognizeStructureFloorParameterDlg::GetStructureFloorCreateParameter() const
{
    return m_param;
}
IDocument* GbmpAutoRecognizeStructureFloorParameterDlg::GetDocument() const
{
    return m_pDocument;
}

